package com.luhe.midi.helper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Stack;

/**
 * Midi工具类
 * byte范围：-128~127
 */
public class MidiUtil {

    //整数转字节
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        //由高位到低位
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    //得到一个整数的变长字节
    public static byte[] writeDynamicBytesUseStack(int value) {

        if (value == 0) {
            byte[] br = {0};
            return br;
        }

        //声明一个栈
        Stack<Byte> stack = new Stack();
        int a = value;
        //转换成128进制过程
        while (a > 0) {
            //余数入栈
            stack.push((byte) (a % 128));
            a = a / 128;
        }
        byte[] b = new byte[stack.size()];

        //余数出栈,非最低位+128
        int i = 0;
        while (!stack.isEmpty()) {
            if (i % 8 == 0) System.out.print(" ");
            if (stack.size() > 1) {
                b[i] = (byte) (stack.pop() + 128);
            } else if (stack.size() == 1) {
                //最低位不加
                b[i] = stack.pop();
            }
            i++;
        }
        return b;
    }

    //得到一个整数的变长字节
    public static byte[] writeDynamicBytes(int value) {
        int len = 1;
        byte[] cache = new byte[4];
        cache[3] = (byte) (value & 0x7f);
        while ((value >>= 7) != 0) {
            ++len;
            cache[4 - len] = (byte) ((value & 0x7f) | 0x80);
        }
        return Arrays.copyOfRange(cache, 4 - len, 4);
    }

    //读动态字节
    public static int readDynamicInt(final byte[] data, int off, int lenLimit) {
        int len = 0; // 动态数据长度
        int t = 0;
        if (lenLimit > 4) {
            lenLimit = 4;
        }
        int offset = 0;
        for (int i = 0; i < lenLimit; ++i) {
            offset = i + off;
            if ((data[offset] & 0x80) != 0) {
                t = (t << 7) + (data[offset] & 0x7f);
            } else {
                len = i + 1;
                return (t << 7) + data[offset];
            }
        }
        // 读取到size上限都未解析出来，表示解析失败了
        return -1;
    }

    //获取动态字节结束的位置,返回-1失败
    public static int readDynamicIntIndex(byte[] bytes) {
        //动态字节结束的位置
        int i = -1;
        for (i = 0; i <= bytes.length - 1; i = i + 1) {
            if (bytes[i] <= 0) i = i + 1;
        }
        return i + 1;
    }

    //从流中获取下一个动态字节整数,最高位为0是动态字节结尾
    public static int readDynamicInt(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int d = 0;
        byte b[] = new byte[1];
        while (inputStream.read(b) != -1) {
            byteArrayOutputStream.write(b);
            if (b[0] >= 0) break;
        }
        int r = MidiUtil.readDynamicInt(byteArrayOutputStream.toByteArray(), 0, 4);
        byteArrayOutputStream.close();
        return r;
    }

    //返回流中下一个动态字节数组
    public static byte[] readDynamicIntBytes(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte b[] = new byte[1];
        while (inputStream.read(b) != -1) {
            byteArrayOutputStream.write(b);
            if (b[0] >= 0) break;
        }
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }


    public static int bytesToInt(final byte[] data, int off, int len) {
        int num = 0;

        int shift = 0;
        for (int i = off + len - 1; i >= off; i--) {
            num += (data[i] & 0xff) << shift;
            shift += 8;
        }
        return num;
    }

    public static byte[] intToBytes(int val, int byteCount, byte[] data, int off) {
        // 数据在 midi file 中按照大端字节序存储
        for (int i = 0; i < byteCount; ++i) {
            data[byteCount - i - 1 + off] = (byte) (val & 0xff);
            val = val >> 8;
        }
        return data;
    }

    public static byte[] intToBytes(int val, byte[] data) {
        return intToBytes(val, data.length, data, 0);
    }

    public static byte[] intToBytes(int val, int byteCount) {
        byte[] d = new byte[byteCount];
        return intToBytes(val, byteCount, d, 0);
    }

    //以16进制打印字节
    public static void printByte(byte b) {
        System.out.print(Integer.toHexString(b));
    }

    //以16进制打印字节数组
    public static void printByteArray(byte b[]) {
        for (byte bs : b) {
            System.out.print(Integer.toHexString(bs) + " ");
        }
    }

    //获取高四位
    public static int getHeight4(byte data) {
        int height;
        height = ((data & 0xf0) >> 4);
        return height;
    }

    //获取低四位
    public static int getLow4(byte data) {
        int low;
        low = (data & 0x0f);
        return low;
    }


    //以16进制打印字节数组
    public static String printByteArray(byte b[], int start, int end, boolean printHex) {
        String log = "";
        for (int i = start; i <= end; i = i + 1) {
            if (printHex) log = log + String.format("%02x", (b[i])) + "\t";
            if (!printHex) log = log + b[i] + "\t";
        }
        return log;
    }

    public static void main(String[] args) {

        byte btes[] = {(byte) 0x80, 0x00};
        for (int i=0;i<=btes.length-1;i=i+1){
            System.out.println(btes[i]);
        }
        int anInt = readDynamicInt(btes, 0, 4);
        System.out.println(anInt);
    }

}
